﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Microsoft.Office.Interop.Excel;
using System.Data;
using System.Data.OleDb;
using System.Xml;
using PatientInformationExtract.MainInterface.Models.XMLCS;
using Microsoft.Win32;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Xml.Xsl;
using PanGu;
using PatientInformationExtract.Dictionary;
using PatientInformationExtract.Dictionary.Views;
using PatientInformationExtract.MainInterface.Views;
using PatientInformationExtract.MainInterface.Models;
using PatientInformationExtract.MainInterface.ViewModels;
using PatientInformationExtract.Components;
using PatientInformationExtract.Dictionary.ViewModels;


namespace PatientInformationExtract.MainInterface.Views
{
    /// <summary>
    /// Interaction logic for Main.xaml
    /// </summary>
    public partial class PatientInformationExtractWindow : System.Windows.Window
    {
        #region Parameter
        private PatientInformationExtract.MainInterface.Models.XMLCS.EventLog _eventLog;
        private PatientInfo _tempPatientInfo;
        private List<string> _patientList;
        private List<ProcessNoteWindow> _processNoteWindows;
        private DictionaryManageViewModel _dictionaryManageViewModel;
        private ContextMenu _cmAddDictionaryWord;

        public delegate void ProcessNoteWindowCloseHandler();
        public event ProcessNoteWindowCloseHandler ProcessNoteWindowCloseEvent;
        public delegate void DictionaryManageHandler();
        public event DictionaryManageHandler DictionaryManageHideEvent;
        public event DictionaryManageHandler DictionaryManageShowEvent;
        public event DictionaryManageHandler DictionaryManageCloseEvent;
        #endregion

        public PatientInformationExtractWindow()
        {
            InitializeComponent();

            _dictionaryManageViewModel = new DictionaryManageViewModel(null);
            _dictionaryManageViewModel.DictionaryManageClosedEvent += new DictionaryManageViewModel.DictionaryManageClosedHandler(dictionaryManage_DictionaryClosedEvent);
            _dictionaryManageViewModel.DictionaryManageSavedEvent += new DictionaryManageViewModel.DictionaryManageSavedHandler(dictionaryManage_DictionaryManageSavedEvent);
            _eventLog = new PatientInformationExtract.MainInterface.Models.XMLCS.EventLog(Singleton<MainInterfaceModel>.Instance.ExcelWorkBooks);
            _eventLog.Option.IsTranslatedToEnglish = true;
            _patientList = new List<string>();
            _processNoteWindows = new List<ProcessNoteWindow>();

            _cmAddDictionaryWord = new ContextMenu();
            System.Windows.Controls.MenuItem miAddToDictionary = new System.Windows.Controls.MenuItem();
            miAddToDictionary.Header = "Add To Dictionary";
            miAddToDictionary.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(miAddToDictionary_PreviewMouseLeftButtonDown);
            _cmAddDictionaryWord.Items.Add(miAddToDictionary);

            dgObservation.ContextMenu = _cmAddDictionaryWord;
            dgMedicalIntervention.ContextMenu = _cmAddDictionaryWord;

            expdProcessNote.IsEnabled = false;
            expdProcessNote.Width = stackPanel_ExpanderArea.Width;
            expdObservation.IsEnabled = false;
            expdObservation.Width = stackPanel_ExpanderArea.Width;
            expdMedicalIntervention.IsEnabled = false;
            expdMedicalIntervention.Width = stackPanel_ExpanderArea.Width;
            expdXML.IsEnabled = false;
            expdXML.Width = stackPanel_ExpanderArea.Width;
            lvwFileList.DisplayMemberPath = "Name";
            lvwFileList.SelectedValuePath = "FullName";
        }

        private void miAddToDictionary_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            IList<DataGridCellInfo> cells = ((((sender as System.Windows.Controls.MenuItem).Parent as ContextMenu).Parent as System.Windows.Controls.Primitives.Popup).PlacementTarget as DataGrid).SelectedCells;
            DataGridCellInfo cell = cells[0];
            _dictionaryManageViewModel.Show();
            string cellContent = (cell.Item as DataRowView)[cell.Column.Header as string].ToString();
            _dictionaryManageViewModel.AddNewWordOutSide(cellContent, "");
        }


        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (ProcessNoteWindowCloseEvent != null)
            {
                this.ProcessNoteWindowCloseEvent();
            }
            this._dictionaryManageViewModel.Close();
        }


        private Stream ParseXmlToHtml(XmlDocument xmlDocument)
        {
            MemoryStream outputStream = new MemoryStream();
            XmlTextWriter writer = new XmlTextWriter(outputStream, System.Text.Encoding.Unicode);
            Singleton<MainInterfaceModel>.Instance.Xslt.Transform(xmlDocument, writer);
            outputStream.Position = 0;
            return outputStream;
        }

        /// <summary>
        /// 进行解析并显示
        /// </summary>
        /// <param name="folderPath">需要解析的病人文件夹路径</param>
        public void ParseFolderAndDisplay(object folderPath)
        {
            DirectoryInfo di = new DirectoryInfo(folderPath.ToString());
            FileInfo[] files = di.GetFiles();
            _tempPatientInfo = null;

            if (_eventLog.PatientInfos.Count != 0)
            {
                foreach (PatientInfo pi in _eventLog.PatientInfos)
                {
                    if (pi.FoderPath == folderPath.ToString())
                    {
                        _tempPatientInfo = pi;
                        break;
                    }
                }
            }

            if (_tempPatientInfo == null)
            {
                _tempPatientInfo = _eventLog.AddPatientInfo();
                try
                {
                    _tempPatientInfo.Initialize(folderPath.ToString());
                    _tempPatientInfo.Update();
                }
                catch (Exception ex)
                {
                    _eventLog.DeletePatientInfoByFolderPath(folderPath.ToString());
                    MessageBox.Show("Can not extract folder " + folderPath.ToString() + ". Error message: " + ex.Message);
                    Dispatcher.BeginInvoke(new System.Action(() =>
                    {
                        DisplayReset();
                        ucWaiting.Visibility = Visibility.Hidden;
                    }), DispatcherPriority.Normal);
                    return;
                }
            }

            Dispatcher.BeginInvoke(new System.Action(() =>
            {
                if (ProcessNoteWindowCloseEvent != null)
                {
                    this.ProcessNoteWindowCloseEvent();
                }

                txtPatientID.Text = _tempPatientInfo.PatientID;
                txtVisitID.Text = _tempPatientInfo.VisitID;
                txtPatientName.Text = _tempPatientInfo.PatientName;
                txtVisitID2.Text = _tempPatientInfo.VisitID2;
                txtAge.Text = _tempPatientInfo.Age;
                txtGender.Text = _tempPatientInfo.Gender;
                expdXML.IsEnabled = true;
                expdXML.IsExpanded = true;
                _tempPatientInfo.XMLDoc.RemoveAll();
                _tempPatientInfo.XMLDoc.AppendChild(_tempPatientInfo.PatientTrace);
                lvwFileList.ItemsSource = files;
                txtFolderPath.Text = _tempPatientInfo.FoderPath;
                wbXML.NavigateToStream(ParseXmlToHtml(_tempPatientInfo.XMLDoc));

                if (_tempPatientInfo.GetObservationTable() != null)
                {
                    dgObservation.ItemsSource = _tempPatientInfo.GetObservationTable().DefaultView;
                    expdObservation.IsEnabled = true;
                }
                if (_tempPatientInfo.GetMedicalInterventionTable() != null)
                {
                    dgMedicalIntervention.ItemsSource = _tempPatientInfo.GetMedicalInterventionTable().DefaultView;
                    expdMedicalIntervention.IsEnabled = true;
                }
                ProcessNoteInfo pni = new ProcessNoteInfo(_tempPatientInfo.XMLDoc);
                foreach (IPatientInfoComponent component in _tempPatientInfo.Components)
                {
                    if (component is IHtmlInfo)
                    {
                        pni = component as ProcessNoteInfo;
                    }
                }
                if (pni.FilePath != null)
                {
                    timeLine.Source = pni.Notes;
                    txtTime.Text = pni.Notes[0].Time;
                    txtType.Text = pni.Notes[0].Type;
                    txtDoctor.Text = pni.Notes[0].Doctor;
                    lvwDiagnosis.ItemsSource = pni.DiagnosisDisplay;
                    StaticMethod.DisplayOnRichTextBox(pni.Notes[0].Words, ref rtbContent);
                    expdProcessNote.IsEnabled = true;
                }
                ucWaiting.Visibility = Visibility.Hidden;
            }), DispatcherPriority.Normal);
        }

        private void tvPatientList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (tvPatientList.SelectedItem != null)
            {
                if ((tvPatientList.SelectedItem as PatientListTreeItem).Tag != null)
                {
                    DisplayReset();
                    ucWaiting.Visibility = Visibility.Visible;
                    Dispatcher.Invoke(new System.Action(() =>
                    {

                    }), System.Windows.Threading.DispatcherPriority.Background);
                    ThreadPool.QueueUserWorkItem(ParseFolderAndDisplay, (tvPatientList.SelectedItem as PatientListTreeItem).Tag.ToString());
                }
            }
        }

        private void btnReset_Click(object sender, RoutedEventArgs e)
        {
            DisplayReset();
        }

        public void DisplayReset()
        {
            expdMedicalIntervention.IsEnabled = false;
            expdMedicalIntervention.IsExpanded = false;
            expdObservation.IsEnabled = false;
            expdProcessNote.IsEnabled = false;
            expdProcessNote.IsExpanded = false;
            expdObservation.IsExpanded = false;
            expdXML.IsEnabled = false;
            expdXML.IsExpanded = false;

            txtPatientID.Text = "";
            txtVisitID.Text = "";
            txtPatientName.Text = "";
            txtVisitID2.Text = "";
            txtAge.Text = "";
            txtGender.Text = "";
            txtFolderPath.Text = "";

            lvwDiagnosis.ItemsSource = null;
            lvwFileList.ItemsSource = null;

            if (this.ProcessNoteWindowCloseEvent != null)
            {
                this.ProcessNoteWindowCloseEvent();
            }

        }

        private void lvwFileList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            Process.Start(lvwFileList.SelectedValue.ToString());
        }

        #region Expander Operation
        private void expdObservation_Expanded(object sender, RoutedEventArgs e)
        {
            expdXML.IsExpanded = false;

            expdObservation.Height = 650;
            expdObservation.Width = stackPanel_ExpanderArea.Width - 25;
            dgObservation.Width = expdObservation.Width;
            dgObservation.Height = expdObservation.Height - 25;
            dgObservation.HorizontalAlignment = HorizontalAlignment.Left;
            dgObservation.VerticalAlignment = VerticalAlignment.Top;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdObservation_Collapsed(object sender, RoutedEventArgs e)
        {
            expdObservation.Height = 25;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdMedicalIntervention_Expanded(object sender, RoutedEventArgs e)
        {
            expdXML.IsExpanded = false;

            expdMedicalIntervention.Height = 650;
            expdMedicalIntervention.Width = stackPanel_ExpanderArea.Width;
            dgMedicalIntervention.Width = expdMedicalIntervention.Width - 25;
            dgMedicalIntervention.Height = expdMedicalIntervention.Height - 25;
            dgMedicalIntervention.HorizontalAlignment = HorizontalAlignment.Left;
            dgMedicalIntervention.VerticalAlignment = VerticalAlignment.Top;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdMedicalIntervention_Collapsed(object sender, RoutedEventArgs e)
        {
            expdMedicalIntervention.Height = 25;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdProcessNote_Expanded(object sender, RoutedEventArgs e)
        {
            expdXML.IsExpanded = false;

            expdProcessNote.Height = 650;
            expdProcessNote.Width = stackPanel_ExpanderArea.Width;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
            timeLine.Focus();
        }

        private void expdProcessNote_Collapsed(object sender, RoutedEventArgs e)
        {
            expdProcessNote.Height = 25;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdXML_Expanded(object sender, RoutedEventArgs e)
        {
            expdMedicalIntervention.IsExpanded = false;
            expdObservation.IsExpanded = false;
            expdProcessNote.IsExpanded = false;

            expdXML.Height = 650;
            expdXML.Width = stackPanel_ExpanderArea.Width;
            wbXML.Width = expdXML.Width - 25;
            wbXML.Height = expdXML.Height - 25;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        private void expdXML_Collapsed(object sender, RoutedEventArgs e)
        {
            expdXML.Height = 25;
            stackPanel_ExpanderArea.Height = expdMedicalIntervention.Height + expdObservation.Height + expdProcessNote.Height + expdXML.Height + 50;
        }

        #endregion

        #region Dictionary
        private void btnDictionary_Click(object sender, RoutedEventArgs e)
        {
            btnDictionary.IsEnabled = false;
            this._dictionaryManageViewModel.Show();
            _dictionaryManageViewModel.Show();
        }

        private void dictionaryManage_DictionaryManageSavedEvent()
        {
            Segment.ReloadDictionary();
            _eventLog.DeleteAllPatientInfo();
            if (txtFolderPath.Text != "")
            {
                ucWaiting.Visibility = Visibility.Visible;
                ThreadPool.QueueUserWorkItem(ParseFolderAndDisplay, txtFolderPath.Text);
                DisplayReset();
            }
        }

        private void dictionaryManage_DictionaryClosedEvent()
        {
            btnDictionary.IsEnabled = true;
        }
        #endregion

        #region ProcessNote
        private void timeLine_TimeLineItemDoubleClickEvent(int selectedIndex)
        {
            ProcessNoteInfo pni = new ProcessNoteInfo(_tempPatientInfo.XMLDoc);
            foreach (IPatientInfoComponent component in _tempPatientInfo.Components)
            {
                if (component is IHtmlInfo)
                {
                    pni = component as ProcessNoteInfo;
                }
            }
            bool alreadyExist = false;
            foreach (ProcessNoteWindow pnw in _processNoteWindows)
            {
                if (pnw.ProcessNoteUnit.Equals(pni.Notes[selectedIndex]))
                {
                    pnw.Focus();
                    alreadyExist = true;
                }
            }
            if (!alreadyExist)
            {
                ProcessNoteWindow window = new ProcessNoteWindow(pni.Notes[selectedIndex], this);
                window.Closing += new System.ComponentModel.CancelEventHandler(ProcessNoteWindow_Closing);
                window.Title += " " + pni.Notes[selectedIndex].Time;
                window.Show();
                _processNoteWindows.Add(window);
            }
        }

        private void timeLine_TimeLineItemSelectedEvent(int selectedIndex)
        {
            ProcessNoteInfo pni = new ProcessNoteInfo(_tempPatientInfo.XMLDoc);
            foreach (IPatientInfoComponent component in _tempPatientInfo.Components)
            {
                if (component is IHtmlInfo)
                {
                    pni = component as ProcessNoteInfo;
                }
            }
            txtTime.Text = "";
            txtType.Text = "";
            txtDoctor.Text = "";
            txtTime.Text = pni.Notes[selectedIndex].Time;
            txtType.Text = pni.Notes[selectedIndex].Type;
            txtDoctor.Text = pni.Notes[selectedIndex].Doctor;
            StaticMethod.DisplayOnRichTextBox(pni.Notes[selectedIndex].Words, ref rtbContent);
        }

        private void rtbContent_IsCheckedChange(object sender, RoutedEventArgs e)
        {
            ProcessNoteInfo pni = new ProcessNoteInfo(_tempPatientInfo.XMLDoc);
            foreach (IPatientInfoComponent component in _tempPatientInfo.Components)
            {
                if (component is IHtmlInfo)
                {
                    pni = component as ProcessNoteInfo;
                }
            }
            StaticMethod.DisplayOnRichTextBox(pni.Notes[timeLine.SelectedIndex].Words, ref rtbContent);
        }

        private void ProcessNoteWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_processNoteWindows.Contains(sender as ProcessNoteWindow))
            {
                _processNoteWindows.Remove(sender as ProcessNoteWindow);
            }
        }
        #endregion

        private void btnLoadEventLog_Click(object sender, RoutedEventArgs e)
        {
            EventLogXMLParser parser = new EventLogXMLParser();
            System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
            openFileDialog.Filter = "XML|*.xml";
            openFileDialog.Title = "Event Log";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    parser.LoadEventLog(openFileDialog.FileName);
                    if (parser.ObservationDataTable.Rows.Count != 0)
                    {
                        expdObservation.IsEnabled = true;
                        dgObservation.ItemsSource = parser.ObservationDataTable.AsDataView();
                    }
                    if (parser.MedicalInterventionDataTable.Rows.Count != 0)
                    {
                        expdMedicalIntervention.IsEnabled = true;
                        dgMedicalIntervention.ItemsSource = parser.MedicalInterventionDataTable.AsDataView();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Parsing " + openFileDialog.FileName + " failed. Error message: " + ex.Message);
                    DisplayReset();
                }
            }
        }

    }

    /// <summary>
    /// 第三方拓展目录树图片功能
    /// </summary>
    class Directory2ImageSource : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            String path = value as String;
            if (System.IO.Directory.Exists(path))
                return ExtractIcon.GetIcon(path, false, true);
            else if (System.IO.File.Exists(path))
                return ExtractIcon.GetIcon(path, false, true);
            return null;
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }
    }
}
